package ReentrantReadWriteLock_4;
import java.util.concurrent.locks.ReentrantReadWriteLock;

class DataProcessor {
    private volatile boolean ready = false;
    private int importantData = 0;
    private final ReentrantReadWriteLock rwLock = new ReentrantReadWriteLock();

    public void prepareData() {
        rwLock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + " 开始准备数据");
            Thread.sleep(100); // 模拟数据准备时间
            importantData = 42;
            ready = true;

            // 降级为读锁
            rwLock.readLock().lock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwLock.writeLock().unlock(); // 释放写锁，保持读锁
        }

        try {
            System.out.println(Thread.currentThread().getName() + " 数据准备完成: " + importantData);
            Thread.sleep(20); // 模拟处理时间
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwLock.readLock().unlock();
        }
    }

    public void useData() {
        rwLock.readLock().lock();
        try {
            if (ready) {
                System.out.println(Thread.currentThread().getName() + " 使用数据: " + importantData);
                Thread.sleep(30); // 模拟使用数据时间
            } else {
                System.out.println(Thread.currentThread().getName() + " 数据未准备好");
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            rwLock.readLock().unlock();
        }
    }
}

public class 读写锁降级_数据一致性保证 {
    public static void main(String[] args) {
        final DataProcessor processor = new DataProcessor();

        // 创建1个数据准备线程
        new Thread(new Runnable() {
            public void run() {
                processor.prepareData();
            }
        }, "数据准备线程").start();

        // 创建20个数据使用线程
        for (int i = 0; i < 20; i++) {
            new Thread(new Runnable() {
                public void run() {
                    processor.useData();
                }
            }, "使用线程-" + i).start();
        }
    }
}